/*  
  
This example reads from the default PCM device  
and writes to standard output for 5 seconds of data.  
  
*/  
  
/* Use the newer ALSA API */  
#define ALSA_PCM_NEW_HW_PARAMS_API  

/* for input report key start  */
    #include <stdio.h>  
    #include <stdlib.h>  
    #include <string.h>  
    #include <unistd.h>  
    #include <fcntl.h>  
    #include <signal.h>  
    #include <limits.h>  
    #include <termios.h>  
    #include <errno.h>  
    #include <linux/input.h>  
  //  #include "log.h"  
      

    #define RCKEY_FILE            "/dev/input/event18"  
/* for input report key end */

#include <alsa/asoundlib.h>  

#define DEBUG_PRINT
#ifdef DEBUG_PRINT
#define Z_LOG(fmt)  printf("ZEWEN: [FUNC]:%s [LINE]:%d "fmt,__FUNCTION__, __LINE__);
#else
#define Z_LOG(fmt)
#endif


snd_pcm_t *handle;  
//char *buffer;  
snd_pcm_hw_params_t *params;  
snd_pcm_uframes_t frames;  
unsigned int val;  
int dir; 
long loops;  
int rc;  
int size;  
int fd = -1;



int device_open(char *device, int mode)
{
/* Open PCM device for recording (capture). */  
//rc = snd_pcm_open(&handle, "default",  
rc = snd_pcm_open(&handle, device, mode, 0);  
if (rc < 0) {  
    fprintf(stderr,  "unableto open pcm device: %s\n",  
            snd_strerror(rc));  
    exit(1);  
}
return 0;
}

  
int device_setparams() 
{  

/* Allocate a hardware parameters object. */  
snd_pcm_hw_params_alloca(&params);  
  
/* Fill it in with default values. */  
snd_pcm_hw_params_any(handle, params);  
  
/* Set the desired hardware parameters. */  
  
/* Interleaved mode */  
snd_pcm_hw_params_set_access(handle, params,  
                      SND_PCM_ACCESS_RW_INTERLEAVED);  
  
/* Signed 16-bit little-endian format */  
snd_pcm_hw_params_set_format(handle, params,  
                              SND_PCM_FORMAT_S16_LE);  
  
/* Two channels (stereo) */  
snd_pcm_hw_params_set_channels(handle, params, 1);  
  
/* 44100 bits/second sampling rate (CD quality) */  
val = 44100;  
//val = 16000;  
snd_pcm_hw_params_set_rate_near(handle, params,  
                                  &val, &dir);  
  
/* Set period size to 32 frames. */  
frames = 32;  
snd_pcm_hw_params_set_period_size_near(handle,  
                              params, &frames, &dir);  
  
/* Write the parameters to the driver */  
rc = snd_pcm_hw_params(handle, params);  
if (rc < 0) {  
    fprintf(stderr,  
            "unable to set hw parameters: %s\n",  
            snd_strerror(rc));  
    exit(1);  
}

   //printf("miles---> [FUNC]:%s [LINE]:%d\n",  __FUNCTION__, __LINE__);
/* Use a buffer large enough to hold one period */  
snd_pcm_hw_params_get_period_size(params,  
                                      &frames, &dir);  
size = frames * 4; /* 2 bytes/sample, 2 channels */  
 // printf("miles---> [FUNC]:%s [LINE]:%d\n",  __FUNCTION__, __LINE__);
/* We want to loop for 5 seconds */  
snd_pcm_hw_params_get_period_time(params,  
                                         &val, &dir);  
//printf("miles---> [FUNC]:%s [LINE]:%d val:%d\n",  __FUNCTION__, __LINE__, val);

return 0;
}
  
int device_capture(void)
{
    char * buffer;
buffer = (char *) malloc(size);  
loops = 5000000 / val;  
 printf("miles---> [FUNC]:%s [LINE]:%d\n",  __FUNCTION__, __LINE__); 
while (loops > 0) {  
    loops--;
	//printf("miles---> [FUNC]:%s [LINE]:%d\n",  __FUNCTION__, __LINE__);
    rc = snd_pcm_readi(handle, buffer, frames);  
	//printf("miles---> [FUNC]:%s [LINE]:%d\n",  __FUNCTION__, __LINE__);
    if (rc == -EPIPE) {  
      /* EPIPE means overrun */  
      fprintf(stderr, "overrun occurred\n");  
      snd_pcm_prepare(handle);  
    } else if (rc < 0) {  
      fprintf(stderr,  
              "error from read: %s\n",  
              snd_strerror(rc));  
    } else if (rc != (int)frames) {  
      fprintf(stderr, "short read, read %d frames\n", rc);  
    }  
	//printf("miles---> [FUNC]:%s [LINE]:%d\n",  __FUNCTION__, __LINE__);
#if 1
    rc = write(fd, buffer, size);  
    if (rc != size)  
      fprintf(stderr,  
              "short write: wrote %d bytes\n", rc);  
    }
#endif
  
snd_pcm_drain(handle);  
snd_pcm_close(handle);  
free(buffer);  
  
return 0;  

}

int device_playback(void)
{
    char *buffer;
 /* Use a buffer large enough to hold one period */
 //  snd_pcm_hw_params_get_period_size(params, &frames, &dir);
    //size = frames * 4; /* 2 bytes/sample, 2 channels */
    buffer = (char *) malloc(size);
    lseek(fd, 0, SEEK_SET);
	
	/* use random data for playback zewen add */
#if 0
	int ii;
	for(ii = 0; ii < size; ii++)
	{
		buffer[ii] = random() & 0xff;
		printf("miles2---> [FUNC]%s [LINE]:%d buff[%d]:%d\n", __FUNCTION__, __LINE__, ii, buffer[ii]);
	}
#endif
    /* We want to loop for 5 seconds */
  //  snd_pcm_hw_params_get_period_time(params,&val, &dir);
    /* 5 seconds in microseconds divided by
    * period time */
    loops = 5000000 / val;
    while (loops > 0) //循环录音 5 s
    {
    loops--;
//	printf("miles2---> [FUNC]%s [LINE]:%d loops:%ld\n", __FUNCTION__, __LINE__, loops);
    
#if 1
	rc = read(fd, buffer, size);
	//printf("miles2---> [FUNC]%s [LINE]:%d loops:%ld buff:%s\n", __FUNCTION__, __LINE__, loops, buffer);
    if (rc == 0) //没有读取到数据
    {
    fprintf(stderr, "end of file on input\n");
    break;
    }
 
    else if (rc != size)//实际读取 的数据 小于 要读取的数据
    {
    fprintf(stderr,"short read: read %d bytes\n", rc);
    }
#endif
    rc = snd_pcm_writei(handle, buffer, frames);//写入声卡 （放音）
    if (rc == -EPIPE)
    {
    /* EPIPE means underrun */
    fprintf(stderr, "underrun occurred\n");
    snd_pcm_prepare(handle);
    } else if (rc < 0) {
    fprintf(stderr,"error from writei: %s\n",snd_strerror(rc));
    } else if (rc != (int)frames) {
    fprintf(stderr,"short write, write %d frames\n", rc);
    }
    }
    snd_pcm_drain(handle);
    snd_pcm_close(handle);
    free(buffer);
    return 0;
}



int main(void)
{
    //int frames = 32;
   // int size = frames * 4;
    
	//buffer = (char *) malloc(32*4);  
    
     //Z_LOG("hello world!\n");
        printf(" -->  time: %s %s %s  now del wavfile!!!<-- \n", __DATE__, __TIME__, "zewen");  
        
        system("rm -f wavfile");
       // sleep(10);
        printf(" -->  time: %s %s %s  wavfile is already delete!!!<-- \n", __DATE__, __TIME__, "zewen");  
	
	//fd = open("./wavfile", O_RDWR|O_CREAT);
	fd = open("./wavfile", O_RDWR);
	if(fd < 0)
	{
		fd = open("./wavfile", O_RDWR|O_CREAT, S_IRWXU|S_IRWXG|S_IRWXO);
		if(fd < 0)
		{
			printf("miles---> [FUNC]:%s [LINE]:%d wavfile open error!! fd=%d errorMessage:%s\n",  __FUNCTION__, __LINE__, fd, strerror(errno));
			return -1;
		}
	}
#if 0
    device_open("hw:0,0", SND_PCM_STREAM_CAPTURE);
    device_setparams();
    device_capture();
#endif

/********** for input report start **********/
#if 1
        int nFd;  
        int nRet;  
        struct input_event *sInputEvent;  
        static int itime;
     
          
        sInputEvent = malloc(sizeof(struct input_event));  
        nFd = open(RCKEY_FILE , O_RDWR);  
        if(nFd < 0)  
        {  
            printf( "open file %s error. errMeg:%s\n", RCKEY_FILE, strerror(errno));  
            return -1;  
        }  
        else  
        {  
            printf("open file %s success.\n", RCKEY_FILE);  
        }  
      
      while(1)
      {
        memset(sInputEvent, 0, sizeof(struct input_event)); 
     
        nRet = read(nFd, sInputEvent, sizeof(struct input_event));  
        if(nRet < 0)  
        {  
            printf("read file %s error.", RCKEY_FILE );  
            return nRet;  
        }  
    
        printf( "type: 0x%x ", sInputEvent->type);  
        printf("code: 0x%x ", sInputEvent->code);  
        printf( "value: 0x%x \n", sInputEvent->value);  
        
        if(sInputEvent->type == EV_KEY && sInputEvent->code == 0xd9 && sInputEvent->value == 0x1)
        {
            printf(" -->  time: %s %s %s <-- \n", __DATE__, __TIME__, "zewen");  
          
            //if(itime == 0)
            {
             //capture
            device_open("hw:1,0", SND_PCM_STREAM_CAPTURE);
            device_setparams();
            device_capture();
            
            //playback
            device_open("default", SND_PCM_STREAM_PLAYBACK);
            device_setparams();
            device_playback();
            }
            
            if(itime == 0)
                itime++;
           // else
                //itime = 0;
        }
      }
#endif
       
/********** for input report end **********/

#if 0
    //capture
    device_open("hw:1,0", SND_PCM_STREAM_CAPTURE);
    device_setparams();
    device_capture();

    //playback
    device_open("default", SND_PCM_STREAM_PLAYBACK);
    device_setparams();
    device_playback();
#endif
    
    lseek(fd, 0, SEEK_SET);
    close(fd);
    
    free(sInputEvent);  
    close(nFd);  
    
    return 0;
}
